/********************************
* name:	数据存储管理模块
* func:	1.采集数据存储（sample文件夹）
*				2.超阈值数据存储（overLimit文件夹）
*				3.日志存储（log文件夹）
*				4.加密数据存储（hideData文件夹）
********************************/
#include "data_storage.h"
#include "time.h"
/*=============================================================================
 * 宏定义和常量配置
 *============================================================================*/

// 文件存储配置
#define MAX_RECORDS_PER_FILE 10     // 每个文件最大存储记录数（题目要求10条）
#define MAX_FILENAME_LEN 64         // 文件名最大长度
#define MAX_DATA_LEN 256            // 单条数据最大长度
#define MAX_LOG_LEN 512             // 日志条目最大长度

// 文件夹路径定义（根据题目要求）
#define SAMPLE_FOLDER_PATH "sample"         // 正常采样数据存储文件夹
#define OVERLIMIT_FOLDER_PATH "overLimit"   // 超限数据存储文件夹
#define LOG_FOLDER_PATH "log"               // 操作日志存储文件夹
#define HIDEDATA_FOLDER_PATH "hideData"     // 加密数据存储文件夹

// Flash存储地址定义
#define BOOT_COUNT_ADDR CONFIG_ADDR_3       // 上电次数存储地址

/*=============================================================================
 * 全局变量定义
 *============================================================================*/

// 外部文件系统对象（在config_manager.c中定义）
extern FATFS user_fs;

// 文件操作对象（每种类型文件都有独立的文件对象）
static FIL sample_file;             // 正常采样数据文件对象
static FIL overlimit_file;          // 超限数据文件对象
static FIL log_file;                // 日志文件对象
static FIL hidedata_file;           // 加密数据文件对象

// 当前文件名缓存（存储当前正在使用的文件名）
static char current_sample_filename[MAX_FILENAME_LEN];      // 当前sample文件名
static char current_overlimit_filename[MAX_FILENAME_LEN];   // 当前overLimit文件名
static char current_log_filename[MAX_FILENAME_LEN];         // 当前log文件名
static char current_hidedata_filename[MAX_FILENAME_LEN];    // 当前hideData文件名

// 文件记录计数器（用于控制何时新建文件）
static int sample_record_count = 10;     // 当前sample文件中的记录数
static int overlimit_record_count = 10;  // 当前overLimit文件中的记录数
static int hidedata_record_count = 10;   // 当前hideData文件中的记录数

// 系统状态变量
static uint32_t boot_count = 0;         // 上电次数计数器（存储在Flash中）

// 文件状态标志（标记各文件是否处于打开状态）
static uint8_t sample_file_open = 0;      // sample文件是否打开
static uint8_t overlimit_file_open = 0;   // overLimit文件是否打开
static uint8_t log_file_open = 0;         // log文件是否打开
static uint8_t hidedata_file_open = 0;    // hideData文件是否打开

// 存储系统初始化标志
static uint8_t storage_system_ready = 0;   // 存储系统是否已初始化

/*=============================================================================
 * 数据结构体定义
 *============================================================================*/

/**
 * 采样数据结构体
 * 包含单次采样的所有相关信息
 */
typedef struct {
    uint32_t timestamp;     // 时间戳（Unix时间戳格式）
    float voltage;          // 电压值（单位：V）
    uint8_t is_overlimit;   // 是否超限标志
    float limit_value;      // 当前设定的限制值（用于超限判断）
} SampleData_t;

/**
 * 日志条目结构体
 * 用于记录系统操作日志
 */


/*=============================================================================
 * 时间和文件名处理函数
 *============================================================================*/

/**
 * @brief 获取当前时间戳并格式化为文件名时间部分
 * @param datetime_str: 输出的时间字符串缓冲区
 * 
 * 格式：YYYYMMDDHHMMSS（14个连续数字）
 * 例如：2025-01-01 00:30:10 → 20250101003010
 * 
 * 使用现有的RTC接口获取时间
 */
void get_datetime_string(char* datetime_str) {
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    
    // 使用现有的RTC接口获取时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化为连续14位数字：年月日时分秒
    sprintf(datetime_str, "%04d%02d%02d%02d%02d%02d",
            current_date.Year + 2000,  // 年份（RTC年份是从2000年开始的）
            current_date.Month,        // 月份
            current_date.Date,         // 日期
            current_time.Hours,        // 小时
            current_time.Minutes,      // 分钟
            current_time.Seconds);     // 秒钟
}

/**
 * @brief 获取当前Unix时间戳
 * @return: 返回当前Unix时间戳
 * 
 * 将RTC时间转换为Unix时间戳格式
 */
uint32_t get_current_timestamp(void) {
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    struct tm time_info;            // 标准时间结构体
    
    // 获取RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 转换为标准时间结构体
    time_info.tm_year = current_date.Year + 2000 - 1900;  // 年份（从1900年开始）
    time_info.tm_mon = current_date.Month - 1;            // 月份（0-11）
    time_info.tm_mday = current_date.Date;                // 日期
    time_info.tm_hour = current_time.Hours;               // 小时
    time_info.tm_min = current_time.Minutes;              // 分钟
    time_info.tm_sec = current_time.Seconds;              // 秒钟
    
    // 转换为Unix时间戳并调整时区（减去8小时）
    time_t timestamp = mktime(&time_info);
    timestamp -= 8 * 3600;  // 调整UTC时区
    
    return (uint32_t)timestamp;
}

/*=============================================================================
 * Flash存储相关函数（用于保存上电次数）
 *============================================================================*/

/**
 * @brief 从Flash读取上电次数
 * @return: 返回存储在Flash中的上电次数
 * 
 * 使用现有的Flash读取接口
 */
uint32_t read_boot_count_from_flash(void) {
    char flash_data[64];            // Flash读取缓冲区
    uint32_t count = 0;             // 上电次数变量
    
    // 清空缓冲区
    memset(flash_data, 0, sizeof(flash_data));
    
    // 使用现有的Flash读取接口
    spi_flash_buffer_read(flash_data, BOOT_COUNT_ADDR, sizeof(flash_data));
    
    // 解析上电次数（格式：boot_count:123）
    sscanf(flash_data, "boot_count:%lu", &count);
    
    return count;
}

/**
 * @brief 将上电次数写入Flash
 * @param count: 要保存的上电次数
 * 
 * 使用现有的Flash写入接口
 */
void write_boot_count_to_flash(uint32_t count) {
    char flash_data[64];            // Flash写入缓冲区
    
    // 格式化上电次数数据
    sprintf(flash_data, "boot_count:%lu", count);
    
    // 使用现有的Flash写入接口
    flash_write(BOOT_COUNT_ADDR, flash_data);
}

/*=============================================================================
 * 文件系统初始化函数
 *============================================================================*/

/**
 * @brief 初始化所有存储文件夹和文件系统
 * @return: 0-成功，-1-失败
 * 
 * 功能：
 * 1. 确保文件系统已挂载
 * 2. 创建所需的四个文件夹
 * 3. 读取并更新上电次数
 * 4. 创建本次上电的日志文件
 */
int tf_test_flag;
int storage_system_init(void) {
    FRESULT fr;     // FatFs函数返回结果
    DIR dir;        // 目录对象，用于检查文件夹是否存在
    
    // 确保文件系统已挂载（使用现有的文件系统对象）
    fr = f_mount(&user_fs, "", 1);
    if (fr != FR_OK) {
        //user_printf(&huart3, "TF卡文件系统挂载失败: %d\r\n", fr);
        return -1;
    }
    
    /*--- 创建sample文件夹（存储正常采样数据）---*/
    fr = f_opendir(&dir, SAMPLE_FOLDER_PATH);
    if (fr != FR_OK) {
        // 文件夹不存在，创建它
        fr = f_mkdir(SAMPLE_FOLDER_PATH);
        if (fr != FR_OK) {
            user_printf(&huart3, "创建sample文件夹失败: %d\r\n", fr);
        } else {
            user_printf(&huart3, "创建sample文件夹成功\r\n");
        }
    }
    f_closedir(&dir);
    
    /*--- 创建overLimit文件夹（存储超限数据）---*/
    fr = f_opendir(&dir, OVERLIMIT_FOLDER_PATH);
    if (fr != FR_OK) {
        fr = f_mkdir(OVERLIMIT_FOLDER_PATH);
        if (fr != FR_OK) {
            user_printf(&huart3, "创建overLimit文件夹失败: %d\r\n", fr);
        } else {
            user_printf(&huart3, "创建overLimit文件夹成功\r\n");
        }
    }
    f_closedir(&dir);
    
    /*--- 创建log文件夹（存储操作日志）---*/
    fr = f_opendir(&dir, LOG_FOLDER_PATH);
    if (fr != FR_OK) {
        fr = f_mkdir(LOG_FOLDER_PATH);
        if (fr != FR_OK) {
            user_printf(&huart3, "创建log文件夹失败: %d\r\n", fr);
        } else {
            user_printf(&huart3, "创建log文件夹成功\r\n");
        }
    }
    f_closedir(&dir);
    
    /*--- 创建hideData文件夹（存储加密数据）---*/
    fr = f_opendir(&dir, HIDEDATA_FOLDER_PATH);
    if (fr != FR_OK) {
        fr = f_mkdir(HIDEDATA_FOLDER_PATH);
        if (fr != FR_OK) {
            user_printf(&huart3, "创建hideData文件夹失败: %d\r\n", fr);
        } else {
            user_printf(&huart3, "创建hideData文件夹成功\r\n");
        }
    }
    f_closedir(&dir);
    
    /*--- 处理上电次数计数器 ---*/
    boot_count = read_boot_count_from_flash();      // 读取当前上电次数
    write_boot_count_to_flash(boot_count+1);      // 增加并保存新的上电次数
    
    /*--- 创建本次上电的日志文件 ---*/
	if(boot_count != 0)
    create_log_file();
    
    // 标记存储系统已就绪
    storage_system_ready = 1;
    
    //user_printf(&huart3, "数据存储系统初始化成功，当前上电次数: %lu\r\n", boot_count);
    return 0;
}

/*=============================================================================
 * 文件创建函数
 *============================================================================*/

/**
 * @brief 创建新的sample数据文件
 * @return: 0-成功，-1-失败
 * 
 * 文件命名规则：sampleData{datetime}.txt
 * 例如：sampleData20250101003010.txt
 */
int create_new_sample_file(void) {
    FRESULT fr;             // FatFs操作结果
    char datetime_str[16];  // 时间字符串缓冲区
    //程序未满但文件关闭
    if(sample_record_count < MAX_RECORDS_PER_FILE)
    {
        //打开当前文件
        fr = f_open(&sample_file, current_sample_filename, FA_OPEN_APPEND | FA_WRITE);
        sample_file_open = 1;  
        return 0;
    }
    // 如果当前有sample文件打开，先关闭它
    if (sample_file_open) {
        f_close(&sample_file);
        sample_file_open = 0;
    }
    if (overlimit_file_open) {
        f_close(&overlimit_file);
        overlimit_file_open = 0;
    }
		if (hidedata_file_open) {
        f_close(&hidedata_file);
        hidedata_file_open = 0;
    }
    
    // 创建并打开新文件（FA_CREATE_ALWAYS表示总是创建新文件）
    // 获取当前时间字符串
	get_datetime_string(datetime_str);
			
	// 构造完整的文件路径和名称

	sprintf(current_sample_filename, "%s/sampleData%s.txt", SAMPLE_FOLDER_PATH, datetime_str);
			
	fr = f_open(&sample_file, current_sample_filename, FA_CREATE_ALWAYS | FA_WRITE);
	if (fr != FR_OK) 
	{
		user_printf(&huart3, "创建sample文件失败: %s, 错误码: %d\r\n", current_sample_filename, fr);
		return -1;
	}
	// 更新文件状态
	sample_file_open = 1;           // 标记文件已打开
	sample_record_count = 0;        // 重置记录计数器
			

	user_printf(&huart3, "创建新sample文件: %s\r\n", current_sample_filename);
	//f_open(&hidedata_file, current_hidedata_filename, FA_OPEN_ALWAYS | FA_WRITE);
	//f_open(&overlimit_file, current_overlimit_filename, FA_OPEN_ALWAYS | FA_WRITE);
    return 0;
}

/**
 * @brief 创建新的overLimit数据文件
 * @return: 0-成功，-1-失败
 * 
 * 文件命名规则：overLimit{datetime}.txt
 * 例如：overLimit20250101003010.txt
 */
int create_new_overlimit_file(void) {
    FRESULT fr;             // FatFs操作结果
    char datetime_str[16];  // 时间字符串缓冲区
     //程序未满但文件关闭
    if(overlimit_record_count < MAX_RECORDS_PER_FILE)
    {
        //打开当前文件
        fr = f_open(&overlimit_file, current_overlimit_filename, FA_OPEN_APPEND | FA_WRITE);
        overlimit_file_open = 1;  
        return 0;
    }
    // 如果当前有overlimit文件打开，先关闭它
    if (overlimit_file_open) 
    {
        f_close(&overlimit_file);
        overlimit_file_open = 0;
    }
    if (hidedata_file_open) 
    {
        f_close(&hidedata_file);
        hidedata_file_open = 0;
    }
	if (sample_file_open) 
    {
        f_close(&sample_file);
        sample_file_open = 0;
    }
    // 获取当前时间字符串
    get_datetime_string(datetime_str);
    
    // 构造完整的文件路径和名称
    sprintf(current_overlimit_filename, "%s/overLimit%s.txt", 
            OVERLIMIT_FOLDER_PATH, datetime_str);
    
    // 创建并打开新文件
    fr = f_open(&overlimit_file, current_overlimit_filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (fr != FR_OK) 
    {
        user_printf(&huart3, "创建overLimit文件失败: %s, 错误码: %d\r\n", current_overlimit_filename, fr);
        return -1;
    }
    
    // 更新文件状态
    overlimit_file_open = 1;        // 标记文件已打开
    overlimit_record_count = 0;     // 重置记录计数器
    
    user_printf(&huart3, "创建新overLimit文件: %s\r\n", current_overlimit_filename);
			//f_open(&hidedata_file, current_hidedata_filename, FA_OPEN_ALWAYS | FA_WRITE);
			//f_open(&sample_file, current_sample_filename, FA_OPEN_ALWAYS | FA_WRITE);
    return 0;
}

/**
 * @brief 创建日志文件
 * @return: 0-成功，-1-失败
 * 
 * 文件命名规则：log{id}.txt
 * 例如：log0.txt, log1.txt, log2.txt...
 * id号基于上电次数，每次上电自动递增
 */
int create_log_file(void) {
    FRESULT fr;     // FatFs操作结果
    
    // 如果当前有log文件打开，先关闭它
    if (log_file_open) {
        f_close(&log_file);
        log_file_open = 0;
    }
    //if(boot_count == 0) return 0;
    // 构造文件名：使用上电次数作为ID
    sprintf(current_log_filename, "%s/log%lu.txt", LOG_FOLDER_PATH, boot_count-1);
    
    // 创建并打开新的日志文件
    fr = f_open(&log_file, current_log_filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (fr != FR_OK) {
        user_printf(&huart3, "创建log文件失败: %s, 错误码: %d\r\n", current_log_filename, fr);
        return -1;
    }
    
    // 更新文件状态
    log_file_open = 1;
    
    //user_printf(&huart3, "创建新log文件: %s\r\n", current_log_filename);
    return 0;
}

/**
 * @brief 创建新的hideData文件
 * @return: 0-成功，-1-失败
 * 
 * 文件命名规则：hideData{datetime}.txt
 * 例如：hideData20250101003010.txt
 */
int create_new_hidedata_file(void) {
    FRESULT fr;             // FatFs操作结果
    char datetime_str[16];  // 时间字符串缓冲区
    //程序未满但文件关闭
    if(hidedata_record_count < MAX_RECORDS_PER_FILE)
    {
        //打开当前文件
        fr = f_open(&hidedata_file, current_hidedata_filename, FA_OPEN_APPEND | FA_WRITE);
        hidedata_file_open = 1;  
        return 0;
    }
    // 如果当前有hidedata文件打开，先关闭它
    if (hidedata_file_open) 
    {
        f_close(&hidedata_file);
        hidedata_file_open = 0;
    }
    if (overlimit_file_open) 
    {
        f_close(&overlimit_file);
        overlimit_file_open = 0;
    }
		if (sample_file_open) {
        f_close(&sample_file);
        sample_file_open = 0;
    }
    // 获取当前时间字符串
    get_datetime_string(datetime_str);
    
    // 构造完整的文件路径和名称
    sprintf(current_hidedata_filename, "%s/hideData%s.txt", 
            HIDEDATA_FOLDER_PATH, datetime_str);
    
    // 创建并打开新文件
    fr = f_open(&hidedata_file, current_hidedata_filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (fr != FR_OK) {
        user_printf(&huart3, "创建hideData文件失败: %s, 错误码: %d\r\n", current_hidedata_filename, fr);
        return -1;
    }
    
    // 更新文件状态
    hidedata_file_open = 1;         // 标记文件已打开
    hidedata_record_count = 0;      // 重置记录计数器
    
    user_printf(&huart3, "创建新hideData文件: %s\r\n", current_hidedata_filename);
		
		//f_open(&overlimit_file, current_overlimit_filename, FA_OPEN_ALWAYS | FA_WRITE);
		//f_open(&sample_file, current_sample_filename, FA_OPEN_ALWAYS | FA_WRITE);
    return 0;
}

/*=============================================================================
 * 数据编码转换函数
 *============================================================================*/

/**
 * @brief 将时间戳和电压值转换为HEX格式
 * @param timestamp: Unix时间戳（4字节）
 * @param voltage: 电压值（浮点数）
 * @param hex_str: 输出的HEX字符串缓冲区
 * 
 * 编码规则（按题目要求）：
 * - 时间戳：4字节HEX（如1735705845 → 6774C4F5）
 * - 电压值：分为两部分
 *   - 整数部分：2字节HEX（如12.5V的12 → 000C）
 *   - 小数部分：2字节HEX（如12.5V的0.5*65536=32768 → 8000）
 * 
 * 示例：2025-01-01 12:30:45 ch0=12.5V → 6774C4F5000C8000
 */
void convert_to_hex_format(uint32_t timestamp, float voltage, char* hex_str) {
    // 时间戳直接转换为32位HEX
    uint32_t ts_hex = timestamp;
    
    // 电压值处理：分离整数和小数部分
    uint16_t voltage_int = (uint16_t)voltage;               // 整数部分
    float voltage_frac = voltage - voltage_int;             // 小数部分
    uint16_t voltage_frac_hex = (uint16_t)(voltage_frac * 65536);   // 小数部分转换为16位整数
    
    // 组合成最终的HEX字符串：时间戳(8位) + 整数部分(4位) + 小数部分(4位)
    sprintf(hex_str, "%08X%04X%04X", ts_hex, voltage_int, voltage_frac_hex);
}

/*=============================================================================
 * 数据保存函数
 *============================================================================*/

/**
 * @brief 保存sample数据（正常采样数据）
 * @param data: 采样数据结构体指针
 * @return: 0-成功，-1-失败
 * 
 * 注意：如果启用了隐藏模式，此函数不会保存数据
 */
int save_sample_data(const SampleData_t* data) {
    FRESULT fr;                     // FatFs操作结果
    UINT bytes_written;             // 实际写入的字节数
    char formatted_data[MAX_DATA_LEN];  // 格式化后的数据字符串
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    
    // 如果启用了隐藏模式，不保存到sample文件夹
    if (output_time_type == 1) {    // output_time_type == 1 表示隐藏模式
        return 0;
    }
    
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }

		
    // 检查是否需要创建新文件（文件未打开或记录数达到上限）
    if (!sample_file_open || sample_record_count >= MAX_RECORDS_PER_FILE) 
	{
        if (create_new_sample_file() != 0) 
        {
            return -1;
        }
    }

    // 获取当前RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化数据字符串（根据题目要求的存储格式）
    sprintf(formatted_data, "%04d-%02d-%02d %02d:%02d:%02d %.2fV%s\r\n",
            current_date.Year + 2000,  // 年份
            current_date.Month,        // 月份
            current_date.Date,         // 日期
            current_time.Hours,        // 小时
            current_time.Minutes,      // 分钟
            current_time.Seconds,      // 秒钟
            data->voltage,             // 电压值（保留两位小数）
            data->is_overlimit ? " OverLimit" : "");    // 如果超限则添加标记
    
    // 写入数据到文件
    fr = f_write(&sample_file, formatted_data, strlen(formatted_data), &bytes_written);
    if (fr != FR_OK) {
        user_printf(&huart3, "写入sample数据失败: %d\r\n", fr);
        return -1;
    }
    
    // 立即同步到存储设备（确保数据不丢失）
    f_sync(&sample_file);
    
    // 增加记录计数器
    sample_record_count++;
    
    return 0;
}

/**
 * @brief 保存超限数据
 * @param data: 采样数据结构体指针
 * @return: 0-成功，-1-失败
 * 
 * 超限数据会单独保存，包含详细的超限信息
 */
int save_overlimit_data(const SampleData_t* data) {
    FRESULT fr;                     // FatFs操作结果
    UINT bytes_written;             // 实际写入的字节数
    char formatted_data[MAX_DATA_LEN];  // 格式化后的数据字符串
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }
    //fr = f_open(&overlimit_file, current_overlimit_filename, FA_READ | FA_WRITE);
    // 检查是否需要创建新文件
    if (!overlimit_file_open || overlimit_record_count >= MAX_RECORDS_PER_FILE) {
        if (create_new_overlimit_file() != 0) {
            return -1;
        }
    }
    
    // 获取当前RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化超限数据（包含超限标记和阈值信息）
    sprintf(formatted_data, "%04d-%02d-%02d %02d:%02d:%02d %.2fV limit %.2f !\r\n",
            current_date.Year + 2000,
            current_date.Month,
            current_date.Date,
            current_time.Hours,
            current_time.Minutes,
            current_time.Seconds,
            data->voltage,              // 当前电压值
            data->limit_value);         // 设定的限制值
    
    // 写入数据
    fr = f_write(&overlimit_file, formatted_data, strlen(formatted_data), &bytes_written);
    if (fr != FR_OK) {
        user_printf(&huart3, "写入overLimit数据失败: %d\r\n", fr);
        return -1;
    }
    
    // 立即同步
    f_sync(&overlimit_file);
    
    // 增加记录计数器
    overlimit_record_count++;
    
    return 0;
}

/**
 * @brief 保存加密数据
 * @param data: 采样数据结构体指针
 * @return: 0-成功，-1-失败
 * 
 * 同时保存原始数据和HEX编码数据用于校验
 */
int save_hidedata(const SampleData_t* data) {
    FRESULT fr;                     // FatFs操作结果
    UINT bytes_written;             // 实际写入的字节数
    char hex_data[32];              // HEX编码数据缓冲区
    char formatted_data[MAX_DATA_LEN];  // 格式化后的数据字符串
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }
     //fr = f_open(&hidedata_file, current_hidedata_filename, FA_READ | FA_WRITE);
    // 检查是否需要创建新文件
    if (!hidedata_file_open || hidedata_record_count >= MAX_RECORDS_PER_FILE) {
        if (create_new_hidedata_file() != 0) 
        {
            return -1;
        }
    }
    
    // 转换为HEX格式
    convert_to_hex_format(data->timestamp, data->voltage, hex_data);
    
    // 获取当前RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化数据（包含原始数据和HEX数据，便于校验准确性）
    sprintf(formatted_data, "%04d-%02d-%02d %02d:%02d:%02d %.2fV\r\nhide: %s%s\r\n",
            current_date.Year + 2000,
            current_date.Month,
            current_date.Date,
            current_time.Hours,
            current_time.Minutes,
            current_time.Seconds,
            data->voltage,                      // 原始电压值
            hex_data,                          // HEX编码数据
            data->is_overlimit ? "*" : "");    // 超限时添加星号标记
    
    // 写入数据
    fr = f_write(&hidedata_file, formatted_data, strlen(formatted_data), &bytes_written);
    if (fr != FR_OK) {
        user_printf(&huart3, "写入hideData失败: %d\r\n", fr);
        return -1;
    }
    
    // 立即同步
    f_sync(&hidedata_file);
    
    // 增加记录计数器
    hidedata_record_count++;
    
    return 0;
}

/**
 * @brief 保存操作日志
 * @param log_entry: 日志条目结构体指针
 * @return: 0-成功，-1-失败
 * 
 * 记录系统的所有操作，用于审计跟踪
 */
/*int save_log_entry(const LogEntry_t* log_entry) {
    FRESULT fr;                     // FatFs操作结果
    UINT bytes_written;             // 实际写入的字节数
    char formatted_log[MAX_LOG_LEN];    // 格式化后的日志字符串
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    
	   if (log_file.obj.fs == NULL) {
        user_printf(&huart3, "文件句柄无效，尝试重新打开\r\n");
        log_file_open = false;
        return -1;
    }
	
	
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }
    
    // 检查日志文件是否打开
    if (!log_file_open) {
        return -1;
    }
		//检查参数有效性
    if (!log_entry || !log_entry->operation || !log_entry->result) {
        user_printf(&huart3, "日志参数无效\r\n");
        return -1;
    }
		//检查字符串长度
		if (strlen(log_entry->operation) > 50 || strlen(log_entry->result) > 100) {
        user_printf(&huart3, "日志内容过长\r\n");
        return -1;
    }
		//清零格式化缓存区
		memset(formatted_log, 0, sizeof(formatted_log));
    // 获取当前RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化日志条目（包含时间、操作和结果）
    sprintf(formatted_log, "[%04d-%02d-%02d %02d:%02d:%02d] %s: %s\r\n",
            current_date.Year + 2000,
            current_date.Month,
            current_date.Date,
            current_time.Hours,
            current_time.Minutes,
            current_time.Seconds,
            log_entry->operation,   // 操作名称
            log_entry->result);     // 操作结果
    
    // 写入日志
    fr = f_write(&log_file, formatted_log, strlen(formatted_log), &bytes_written);
    if (fr != FR_OK) {
         user_printf(&huart3, "写入log失败: FR=%d, 长度=%d, 实际写入=%d\r\n", 
               fr, strlen(formatted_log), bytes_written);
        return -1;
    }
    
    // 立即同步（日志数据很重要，需要及时保存）
    f_sync(&log_file);
    
    return 0;
}*/
/**
 * @brief 保存操作日志
 * @param log_entry: 日志条目结构体指针
 * @return: 0-成功，-1-失败
 * 
 * 记录系统的所有操作，用于审计跟踪
 */
int save_log_entry(const LogEntry_t* log_entry) {
    FRESULT fr;                     // FatFs操作结果
    UINT bytes_written;             // 实际写入的字节数
    char formatted_log[MAX_LOG_LEN];    // 格式化后的日志字符串
    RTC_TimeTypeDef current_time;   // RTC时间结构体
    RTC_DateTypeDef current_date;   // RTC日期结构体
    //FIL log_file_temp;
		
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }
    
    // 检查日志文件是否打开
    if (!log_file_open) {
        return -1;
    }
    // 获取当前RTC时间
    rtc_get_time_info(&current_time, &current_date);
    
    // 格式化日志条目（包含时间、操作和结果）
    sprintf(formatted_log, "%04d-%02d-%02d %02d:%02d:%02d %s: %s\r\n",
            current_date.Year + 2000,
            current_date.Month,
            current_date.Date,
            current_time.Hours,
            current_time.Minutes,
            current_time.Seconds,
            log_entry->operation,   // 操作名称
            log_entry->result);     // 操作结果
    
    // 写入日志
	//user_printf(&huart3, "Before log: ready=%d, open=%d\r\n", storage_system_ready, log_file_open);
    fr = f_write(&log_file, formatted_log, strlen(formatted_log), &bytes_written);
    if (fr != FR_OK) 
		{
        user_printf(&huart3, "写入log失败: %d\r\n", fr);
        return -1;
    }
    
    // 立即同步（日志数据很重要，需要及时保存）
    f_sync(&log_file);
		
    return 0;
}
/*=============================================================================
 * 主要接口函数
 *============================================================================*/

/**
 * @brief 主要的数据存储接口函数
 * @param voltage: 当前电压值
 * @param limit_value: 设定的限制阈值
 * @param timestamp: 当前时间戳
 * @return: 0-成功，-1-失败
 * 
 * 此函数是数据存储的主入口，会根据当前模式和数据特性
 * 决定数据的存储位置和格式
 */
int store_sampling_data(float voltage, float limit_value, uint32_t timestamp) {
    SampleData_t data;      // 采样数据结构体
    LogEntry_t log_entry;   // 日志条目结构体
    uint8_t is_overlimit = (voltage > limit_value) ? 1 : 0;  // 判断是否超限
    
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return -1;
    }
    
    /*--- 填充采样数据结构体 ---*/
    data.timestamp = timestamp;         // 时间戳
    data.voltage = voltage;             // 电压值
    data.is_overlimit = is_overlimit;   // 超限标志
    data.limit_value = limit_value;     // 限制值
    //先关闭当前文件夹
    storage_system_close();
    /*--- 根据模式保存数据 ---*/
    if (output_time_type == 1) 
    {
        // 隐藏模式：保存到hideData文件夹
    save_hidedata(&data);
    } 
    else 
    {
        // 正常模式：保存到sample文件夹
        save_sample_data(&data);
    }
    
    /*--- 如果超限，保存到overLimit文件夹 ---*/
    if (is_overlimit) 
    {
        storage_system_close();
        save_overlimit_data(&data);
    }
    
    /*--- 记录操作日志 ---*/
    log_entry.timestamp = timestamp;
    strcpy(log_entry.operation, "data sample");   // 操作类型
    sprintf(log_entry.result, "voltage=%.2fv, overlimit=%s", 
            voltage, is_overlimit ? "yes" : "no");  // 操作结果
    save_log_entry(&log_entry);
    
    return 0;
}

/**
 * @brief 记录操作日志的便捷接口
 * @param operation: 操作名称
 * @param result: 操作结果描述
 * 
 * 用于记录各种系统操作，如配置更改、命令执行等
 */
void storage_log_operation(const char* operation, const char* result) {
    LogEntry_t log_entry;   // 日志条目结构体
    
    // 检查存储系统是否已初始化
    if (!storage_system_ready) {
        return;
    }
    
    // 填充日志信息
    log_entry.timestamp = get_current_timestamp();  // 使用当前时间
    strncpy(log_entry.operation, operation, sizeof(log_entry.operation) - 1);
    log_entry.operation[sizeof(log_entry.operation) - 1] = '\0';  // 确保字符串结束
    
    strncpy(log_entry.result, result, sizeof(log_entry.result) - 1);
    log_entry.result[sizeof(log_entry.result) - 1] = '\0';
    
    // 保存日志条目
    save_log_entry(&log_entry);
}

/**
 * @brief 数据存储任务函数（集成到调度器）
 * 
 * 当采样状态为开启且需要存储数据时调用
 * 此函数会被添加到调度器任务数组中
 */
void data_storage_task(void) {
    // 检查是否有采样数据需要存储
    if (data_stored_flag == 1) {  // 采样状态开启
        // 获取当前时间戳
        uint32_t current_timestamp = get_current_timestamp();
        
        // 获取当前电压值和限制值
        float current_voltage = volatage;          // 使用全局电压变量
        float current_limit = user_ctr.limit;     // 使用全局配置变量
        
        // 存储采样数据
        store_sampling_data(current_voltage, current_limit, current_timestamp);
				data_stored_flag = 0;
    }
}

/**
 * @brief 关闭所有文件和存储系统
 * 
 * 在系统关闭前调用，确保所有文件正确关闭
 */
void storage_system_close(void) 
{
    // 关闭sample文件
    if (sample_file_open) {
        f_close(&sample_file);
        sample_file_open = 0;
    }
    
    // 关闭overlimit文件
    if (overlimit_file_open) {
        f_close(&overlimit_file);
        overlimit_file_open = 0;
    }

    // 关闭hidedata文件
    if (hidedata_file_open) {
        f_close(&hidedata_file);
        hidedata_file_open = 0;
    }
    
}

int log_operation(const char* operation, const char* result) 
{
    LogEntry_t log_entry;

    // 确保操作和结果字符串不超过最大长度
    if (strlen(operation) >= sizeof(log_entry.operation) || strlen(result) >= sizeof(log_entry.result)) 
		{
        user_printf(&huart3, "操作或结果字符串过长，无法记录日志\r\n");
        return -1;
    }

    // 设置操作类型和结果
    strcpy(log_entry.operation, operation);
    sprintf(log_entry.result, "%s", result);

    // 调用保存日志函数
    return save_log_entry(&log_entry);
}
